home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 175 (1991-09-10)(Manewaldt, A.)(DE)(PD).zip / Taifun 175 (1991-09-10)(Manewaldt, A.)(DE)(PD).adf / Term / Source.LZH / SaveILBM.c < prev    next >
C/C++ Source or Header  |  1991-07-06  |  13KB  |  593 lines

  1. /* $Revision Header * Header built automatically - do not edit! *************
  2.  *
  3.  *    (C) Copyright 1985-1990 by Jim Kent & Olaf `Olsen' Barthel
  4.  *
  5.  *    Name .....: SaveILBM.c
  6.  *    Created ..: Monday 21-Jan-91 20:12
  7.  *    Revision .: 0
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    21-Jan-91       Olsen           Modified this file!
  12.  *
  13.  * $Revision Header ********************************************************/
  14.  
  15. #include "TermGlobal.h"
  16.  
  17.     /* This is basically Jim Kent's IFF-ILBM writer. Changes I made:
  18.      *
  19.      * - Put all support files into a single file.
  20.      * - Added iffparse.library function calls.
  21.      * - Added the CAMG chunk and implemented 32 bit viewmode IDs.
  22.      * - Wrote a small routine to save the data.
  23.      * - Changed the way the original source code was indented and
  24.      *   the names of some variables.
  25.      */
  26.  
  27.     /* A bitmap header. */
  28.  
  29. struct BitMapHeader
  30. {
  31.     UWORD w, h;            /* raster width & height in pixels */
  32.     UWORD x, y;            /* position for this image */
  33.     UBYTE nPlanes;            /* # source bitplanes */
  34.     UBYTE masking;            /* masking technique */
  35.     UBYTE compression;        /* compression algoithm */
  36.     UBYTE pad1;            /* UNUSED.  For consistency, put 0 here.*/
  37.     UWORD transparentColor;        /* transparent "color number" */
  38.     UBYTE xAspect, yAspect;        /* aspect ratio, a rational number x/y */
  39.     WORD pageWidth, pageHeight;    /* source "page" size in pixels */
  40. };
  41.  
  42.     /* Compression status. */
  43.  
  44. #define DUMP    0
  45. #define RUN    1
  46.  
  47.     /* Run length encoding constants. */
  48.  
  49. #define MINRUN    3
  50. #define MAXRUN    128
  51. #define MAXDAT    128
  52.  
  53.     /* Size of the IFF write cache. */
  54.  
  55. #define IFF_SIZE    4096
  56.  
  57.     /* Cache and cache index. */
  58.  
  59. STATIC UBYTE IFFBuffer[IFF_SIZE];
  60. STATIC SHORT IFFSize;
  61.  
  62.     /* FlushIFF(struct IFFHandle *IFFHandle):
  63.      *
  64.      *    Flush the contents of the IFF write cache.
  65.      */
  66.  
  67. STATIC BYTE
  68. FlushIFF(struct IFFHandle *IFFHandle)
  69. {
  70.     if(IFFSize)
  71.     {
  72.         if(WriteChunkBytes(IFFHandle,IFFBuffer,IFFSize) != IFFSize)
  73.         {
  74.             IFFSize = 0;
  75.             return(FALSE);
  76.         }
  77.  
  78.         IFFSize = 0;
  79.     }
  80.  
  81.     return(TRUE);
  82. }
  83.  
  84.     /* PutIFF(struct IFFHandle *IFFHandle,UBYTE c):
  85.      *
  86.      *    Send a single byte to the IFF write cache.
  87.      */
  88.  
  89. STATIC BYTE
  90. PutIFF(struct IFFHandle *IFFHandle,UBYTE c)
  91. {
  92.     if(IFFSize == IFF_SIZE)
  93.         if(!FlushIFF(IFFHandle))
  94.             return(FALSE);
  95.  
  96.     IFFBuffer[IFFSize++] = c;
  97.  
  98.     return(TRUE);
  99. }
  100.  
  101.     /* WriteIFF(struct IFFHandle *IFFHandle,UBYTE *Data,SHORT Size):
  102.      *
  103.      *    Write a buffer to the IFF cache.
  104.      */
  105.  
  106. STATIC BYTE
  107. WriteIFF(struct IFFHandle *IFFHandle,UBYTE *Data,LONG Size)
  108. {
  109.     LONG Len;
  110.  
  111.     while(Size)
  112.     {
  113.         if(IFFSize == IFF_SIZE)
  114.             if(!FlushIFF(IFFHandle))
  115.                 return(FALSE);
  116.  
  117.         if((Len = Size) > IFF_SIZE - IFFSize)
  118.             Len = IFF_SIZE - IFFSize;
  119.  
  120.         CopyMem(&Data[0],&IFFBuffer[IFFSize],Len);
  121.  
  122.         IFFSize    += Len;
  123.         Size    -= Len;
  124.  
  125.         Data = &Data[Len];
  126.     }
  127.  
  128.     return(TRUE);
  129. }
  130.  
  131. STATIC LONG
  132. PackRow(struct IFFHandle *FileHandle,UBYTE *Source,LONG Size)
  133. {
  134.     UBYTE    c,LastByte = 0;
  135.     BYTE    CompMode = DUMP;
  136.     SHORT    InBuf = 1;            /* number of chars in buffer */
  137.     SHORT    RunStart = 0;            /* buffer index current run starts */
  138.     LONG    PutSize = 0;
  139.     UBYTE    LineBuf[MAXDAT*3/2];        /* I think MAXDAT+1 would suffice */
  140.  
  141.     LineBuf[0] = LastByte = *Source++;    /* so have valid LastByte */
  142.     Size--;                    /* since one byte eaten. */
  143.  
  144.     for( ; Size ; --Size)
  145.     {
  146.         LineBuf[InBuf++] = c = *Source++;
  147.  
  148.         switch(CompMode)
  149.         {
  150.             case DUMP:    /* If the buffer is full, write the length byte, then the data */
  151.  
  152.                     if(InBuf > MAXDAT)
  153.                     {
  154.                         if(!PutIFF(FileHandle,InBuf-2))
  155.                             return(FALSE);
  156.  
  157.                         if(!WriteIFF(FileHandle,LineBuf,InBuf-1))
  158.                             return(0);
  159.  
  160.                         PutSize += InBuf;
  161.                         LineBuf[0] = c;
  162.                         InBuf = 1;
  163.                         RunStart = 0;
  164.                         break;
  165.                     }
  166.  
  167.                     if(c == LastByte)
  168.                     {
  169.                         if(InBuf - RunStart >= MINRUN)
  170.                         {
  171.                             if(RunStart > 0)
  172.                             {
  173.                                 if(!PutIFF(FileHandle,RunStart-1))
  174.                                     return(FALSE);
  175.  
  176.                                 if(!WriteIFF(FileHandle,LineBuf,RunStart))
  177.                                     return(0);
  178.  
  179.                                 PutSize += RunStart+1;
  180.                             }
  181.  
  182.                             CompMode = RUN;
  183.                         }
  184.                         else
  185.                         {
  186.                             if(!RunStart)
  187.                                 CompMode = RUN;
  188.                         }
  189.  
  190.                             /* no dump in progress, so can't lose by making
  191.                                these 2 a run. */
  192.                     }
  193.                     else
  194.                         RunStart = InBuf - 1;/* first of run */
  195.  
  196.                     break;
  197.  
  198.             case RUN:    if((c != LastByte) ||(InBuf - RunStart > MAXRUN))
  199.                     {
  200.                         /* output run */
  201.  
  202.                         if(!PutIFF(FileHandle,-(InBuf - RunStart - 2)))
  203.                             return(FALSE);
  204.  
  205.                         if(!PutIFF(FileHandle,LastByte))
  206.                             return(FALSE);
  207.  
  208.                         PutSize += 2;
  209.  
  210.                         LineBuf[0] = c;
  211.                         InBuf = 1;
  212.                         RunStart = 0;
  213.                         CompMode = DUMP;
  214.                     }
  215.  
  216.                     break;
  217.         }
  218.  
  219.         LastByte = c;
  220.     }
  221.  
  222.     switch(CompMode)
  223.     {
  224.         case DUMP:    if(!PutIFF(FileHandle,InBuf-1))
  225.                     return(FALSE);
  226.  
  227.                 if(!WriteIFF(FileHandle,LineBuf,InBuf))
  228.                     return(FALSE);
  229.  
  230.                 PutSize += InBuf+1;
  231.                 break;
  232.  
  233.         case RUN:    if(!PutIFF(FileHandle,-(InBuf - RunStart - 1)))
  234.                     return(FALSE);
  235.  
  236.                 if(!PutIFF(FileHandle,LastByte))
  237.                     return(FALSE);
  238.  
  239.                 PutSize += 2;
  240.                 break;
  241.     }
  242.  
  243.     return(PutSize);
  244. }
  245.  
  246. STATIC LONG
  247. PackBitMap(struct IFFHandle *FileHandle,struct BitMap *BitMap,LONG Height)
  248. {
  249.     LONG i,j,RowLength,CompressedLength = 0,PlaneOffset = 0;
  250.  
  251.     for(i = 0 ; i < Height ; i++)
  252.     {
  253.         for(j = 0 ; j < BitMap -> Depth ; j++)
  254.         {
  255.             if(!(RowLength = PackRow(FileHandle,BitMap -> Planes[j] + PlaneOffset,BitMap -> BytesPerRow)))
  256.                 return(0);
  257.  
  258.             CompressedLength += RowLength;
  259.         }
  260.  
  261.         PlaneOffset += BitMap -> BytesPerRow;
  262.     }
  263.  
  264.     return(CompressedLength);
  265. }
  266.  
  267. STATIC BYTE
  268. WriteILBM(UBYTE *FileName,UBYTE *Colours,struct BitMap *BitMap,LONG OffsetX,BYTE OffsetY,LONG Width,LONG Height,LONG Compressed,LONG PageWidth,LONG PageHeight,ULONG ViewModes)
  269. {
  270.     struct IFFHandle    *FileHandle;
  271.     struct BitMapHeader     BitMapHeader;
  272.     LONG             RowOffset;
  273.     LONG             i,j;
  274.     SHORT             NumColours = 32;
  275.     BYTE             Success = TRUE;
  276.  
  277.     if(BitMap)
  278.     {
  279.         if((NumColours = 1 << BitMap -> Depth) > 32)
  280.             NumColours = 32;
  281.  
  282.         if(ViewModes & HAM)
  283.             NumColours = 16;
  284.     }
  285.  
  286.     if(FileHandle = AllocIFF())
  287.     {
  288.         if(FileHandle -> iff_Stream = Open(FileName,MODE_NEWFILE))
  289.         {
  290.             InitIFFasDOS(FileHandle);
  291.  
  292.             if(!OpenIFF(FileHandle,IFFF_WRITE))
  293.             {
  294.                 /* say its a FORM ILBM */
  295.  
  296.                 if(!PushChunk(FileHandle,'ILBM','FORM',IFFSIZE_UNKNOWN))
  297.                 {
  298.                     /* initialize the BitMapHeader to normal values */
  299.  
  300.                     BitMapHeader . masking        = 0;
  301.                     BitMapHeader . pad1        = 0;
  302.                     BitMapHeader . transparentColor    = 0;
  303.  
  304.                     if(Compressed)
  305.                         BitMapHeader . compression = 1;
  306.                     else
  307.                         BitMapHeader . compression = 0;
  308.  
  309.                     BitMapHeader . pageWidth    = PageWidth;
  310.                     BitMapHeader . pageHeight    = PageHeight;
  311.                     BitMapHeader . yAspect        = 11;
  312.  
  313.                     /* mask out all unwanted bits. */
  314.  
  315.                     ViewModes &= ~(SPRITES | VP_HIDE | GENLOCK_AUDIO | GENLOCK_VIDEO);
  316.  
  317.                     if((ViewModes & HIRES) && (ViewModes & LACE))
  318.                         BitMapHeader . xAspect = 10;
  319.  
  320.                     if(!(ViewModes & HIRES) && (ViewModes & LACE))
  321.                         BitMapHeader . xAspect = 20;
  322.  
  323.                     if((ViewModes & HIRES) && !(ViewModes & LACE))
  324.                         BitMapHeader . xAspect = 5;
  325.  
  326.                     if(!(ViewModes & HIRES) && !(ViewModes & LACE))
  327.                         BitMapHeader . xAspect = 10;
  328.  
  329.                     /* if it's not just a color map give the dimensions of rasters */
  330.  
  331.                     if(BitMap)
  332.                     {
  333.                         BitMapHeader . w    = Width;
  334.                         BitMapHeader . h    = Height;
  335.                         BitMapHeader . nPlanes    = BitMap -> Depth;
  336.                         BitMapHeader . x    = OffsetX;
  337.                         BitMapHeader . y    = OffsetY;
  338.                     }
  339.  
  340.                     if(!PushChunk(FileHandle,0,'BMHD',IFFSIZE_UNKNOWN))
  341.                     {
  342.                         if(WriteChunkBytes(FileHandle,&BitMapHeader,sizeof(BitMapHeader)) == sizeof(BitMapHeader))
  343.                         {
  344.                             if(!PopChunk(FileHandle))
  345.                             {
  346.                                 if(!PushChunk(FileHandle,0,'CMAP',IFFSIZE_UNKNOWN))
  347.                                 {
  348.                                     if(WriteChunkBytes(FileHandle,Colours,3 * NumColours) == 3 * NumColours)
  349.                                     {
  350.                                         if(!PopChunk(FileHandle))
  351.                                         {
  352.                                             if(!PushChunk(FileHandle,0,'CAMG',IFFSIZE_UNKNOWN))
  353.                                             {
  354.                                                 if(WriteChunkBytes(FileHandle,&ViewModes,sizeof(ULONG)) == sizeof(ULONG))
  355.                                                 {
  356.                                                     if(!PopChunk(FileHandle))
  357.                                                     {
  358.                                                         if(!PushChunk(FileHandle,0,'BODY',IFFSIZE_UNKNOWN))
  359.                                                         {
  360.                                                             if(Compressed)
  361.                                                             {
  362.                                                                 if(!PackBitMap(FileHandle,BitMap,Height))
  363.                                                                     Success = FALSE;
  364.                                                                 else
  365.                                                                 {
  366.                                                                     if(!FlushIFF(FileHandle))
  367.                                                                         Success = FALSE;
  368.                                                                 }
  369.                                                             }
  370.                                                             else
  371.                                                             {
  372.                                                                 i = Height;
  373.                                                                 RowOffset = 0;
  374.  
  375.                                                                 while(--i >= 0 && Success)
  376.                                                                 {
  377.                                                                     for(j = 0 ; j < BitMap -> Depth ; j++)
  378.                                                                     {
  379.                                                                         if(WriteChunkBytes(FileHandle,BitMap -> Planes[j] + RowOffset,Height) != Height)
  380.                                                                         {
  381.                                                                             Success = FALSE;
  382.                                                                             break;
  383.                                                                         }
  384.  
  385.                                                                         RowOffset += BitMap -> BytesPerRow;
  386.                                                                     }
  387.                                                                 }
  388.                                                             }
  389.  
  390.                                                             if(PopChunk(FileHandle))
  391.                                                                 Success = FALSE;
  392.                                                         }
  393.                                                         else
  394.                                                             Success = FALSE;
  395.                                                     }
  396.                                                     else
  397.                                                         Success = FALSE;
  398.                                                 }
  399.                                                 else
  400.                                                     Success = FALSE;
  401.                                             }
  402.                                             else
  403.                                                 Success = FALSE;
  404.                                         }
  405.                                         else
  406.                                             Success = FALSE;
  407.                                     }
  408.                                     else
  409.                                         Success = FALSE;
  410.                                 }
  411.                                 else
  412.                                     Success = FALSE;
  413.                             }
  414.                             else
  415.                                 Success = FALSE;
  416.                         }
  417.                         else
  418.                             Success = FALSE;
  419.                     }
  420.                     else
  421.                         Success = FALSE;
  422.  
  423.                     if(PopChunk(FileHandle))
  424.                         Success = FALSE;
  425.                 }
  426.                 else
  427.                     Success = FALSE;
  428.             }
  429.             else
  430.                 Success = FALSE;
  431.  
  432.             Close(FileHandle -> iff_Stream);
  433.         }
  434.         else
  435.             Success = FALSE;
  436.  
  437.         FreeIFF(FileHandle);
  438.     }
  439.     else
  440.         Success = FALSE;
  441.  
  442.     return(Success);
  443. }
  444.  
  445.     /* SaveRPort():
  446.      *
  447.      *    Save the contents of a given RastPort to an IFF-ILBM
  448.      *    file, use iffparse.library to get the job done.
  449.      */
  450.  
  451. LONG
  452. SaveRPort(struct RastPort *RPort,struct ViewPort *VPort,LONG LeftEdge,LONG TopEdge,LONG Width,LONG Height,LONG ParentWidth,LONG ParentHeight,LONG Cookie,STRPTR Name)
  453. {
  454.     UBYTE         ColTable[32 * 3];
  455.     struct BitMap     DstMap,*SMap = RPort -> BitMap;
  456.     LONG         IFF_Result,i,r,g,b;
  457.  
  458.     LONG         PacketDims[4];
  459.     BYTE         ClosedWindow = FALSE;
  460.  
  461.         /* It is impossible to drag the packet window to
  462.          * a place where it doesn't overlap the main window.
  463.          * To avoid unpleasant effects we'll close it
  464.          * and reopen it after saving the main window
  465.          * contents.
  466.          */
  467.  
  468.     if(PacketWindow)
  469.     {
  470.         PacketDims[0] = PacketWindow -> LeftEdge;
  471.         PacketDims[1] = PacketWindow -> TopEdge;
  472.         PacketDims[2] = PacketWindow -> Width;
  473.         PacketDims[3] = PacketWindow -> Height;
  474.  
  475.         PacketWindow -> Flags |= WFLG_RMBTRAP;
  476.  
  477.         ClearMenuStrip(PacketWindow);
  478.  
  479.         CloseWindow(PacketWindow);
  480.  
  481.         PacketWindow = NULL;
  482.  
  483.         ClosedWindow = TRUE;
  484.     }
  485.  
  486.         /* Reset buffer counter. */
  487.  
  488.     IFFSize = 0;
  489.  
  490.         /* Perform `cookie cut'? */
  491.  
  492.     if(LeftEdge || TopEdge || Cookie)
  493.     {
  494.         Cookie = TRUE;
  495.  
  496.         InitBitMap(&DstMap,SMap -> Depth,Width,Height);
  497.  
  498.         for(i = 0 ; i < SMap -> Depth ; i++)
  499.         {
  500.             if(!(DstMap . Planes[i] = (PLANEPTR)AllocMem(DstMap . BytesPerRow * DstMap . Rows,MEMF_CHIP | MEMF_CLEAR)))
  501.             {
  502.                 IFF_Result = FALSE;
  503.                 goto Stop;
  504.             }
  505.         }
  506.  
  507.         BltBitMap(SMap,LeftEdge,TopEdge,&DstMap,0,0,Width,Height,0xC0,0xFF,NULL);
  508.  
  509.         SMap = &DstMap;
  510.     }
  511.  
  512.         /* Convert the colours. */
  513.  
  514.     for(i = 0 ; i < 32 ; i++)
  515.     {
  516.         UWORD TmpCol = GetRGB4(VPort -> ColorMap,i);
  517.  
  518.         r = (TmpCol >> 8) & 0xF;
  519.         g = (TmpCol >> 4) & 0xF;
  520.         b = (TmpCol     ) & 0xF;
  521.  
  522.         ColTable[i * 3 + 0] = r << 4;
  523.         ColTable[i * 3 + 1] = g << 4;
  524.         ColTable[i * 3 + 2] = b << 4;
  525.     }
  526.  
  527.         /* Write the IFF-ILBM file. */
  528.  
  529.     IFF_Result = WriteILBM(Name,ColTable,SMap,LeftEdge,TopEdge,Width,Height,TRUE,ParentWidth,ParentHeight,GetVPModeID(VPort));
  530.  
  531.         /* Free the display cookie. */
  532.  
  533. Stop:    if(Cookie)
  534.     {
  535.         for(i = 0 ; i < DstMap . Depth ; i++)
  536.         {
  537.             if(DstMap . Planes[i])
  538.                 FreeMem(DstMap . Planes[i],DstMap . BytesPerRow * DstMap . Rows);
  539.         }
  540.     }
  541.  
  542.         /* Delete truncated file or set the `not executable' bit
  543.          * if successful.
  544.          */
  545.  
  546.     if(!IFF_Result)
  547.         DeleteFile(Name);
  548.     else
  549.         SetProtection(Name,FIBF_EXECUTE);
  550.  
  551.         /* Be a good boy and reopen the packet window. */
  552.  
  553.     if(ClosedWindow)
  554.     {
  555.         if(PacketWindow = OpenWindowTags(NULL,
  556.             WA_Left,    PacketDims[0],
  557.             WA_Top,        PacketDims[1],
  558.  
  559.             WA_Width,    PacketDims[2],
  560.             WA_Height,    PacketDims[3],
  561.  
  562.             WA_Activate,    TRUE,
  563.             WA_DragBar,    TRUE,
  564.             WA_DepthGadget,    TRUE,
  565.             WA_CloseGadget,    TRUE,
  566.             WA_RMBTrap,    TRUE,
  567.             WA_SizeGadget,    TRUE,
  568.             WA_MinWidth,    80,
  569.             WA_MinHeight,    27,
  570.             WA_MaxWidth,    Screen -> Width,
  571.             WA_MaxHeight,    27,
  572.             WA_CustomScreen,Screen,
  573.  
  574.             WA_IDCMP,    STRINGIDCMP | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_ACTIVEWINDOW | IDCMP_RAWKEY,
  575.  
  576.             WA_Title,    "Packet Window",
  577.         TAG_DONE))
  578.         {
  579.             AddGList(PacketWindow,PacketGadgetList,(UWORD)-1,(UWORD)-1,NULL);
  580.             RefreshGList(PacketGadgetList,PacketWindow,NULL,(UWORD)-1);
  581.             GT_RefreshWindow(PacketWindow,NULL);
  582.  
  583.             SetMenuStrip(PacketWindow,PacketMenu);
  584.  
  585.             PacketWindow -> Flags &= ~WFLG_RMBTRAP;
  586.         }
  587.         else
  588.             DeletePacketWindow();
  589.     }
  590.  
  591.     return(IFF_Result);
  592. }
  593.